package test.unit
{
	import com.zanshine.benchmark.api.Benchmarkable;
	import com.zanshine.benchmark.core.CaseRunner;
	import com.zanshine.benchmark.core.TestResult;
	import com.zanshine.benchmark.core.events.BenchmarkEvent;
	
	import flash.utils.Dictionary;
	import flash.utils.getQualifiedClassName;
	
	import net.digitalprimates.fluint.tests.TestCase;
	
	import mx.utils.StringUtil;
	
	import test.mock.*;

	public class ResultAfterRunningBenchsTest extends TestCase
	{
		private var benchTest:Benchmarkable;
		private var benchRunner:CaseRunner;
		
		override protected function setUp():void
		{
			benchTest = new SimpleBenchTestMock;
			benchRunner = new CaseRunner(benchTest);
			//benchRunner.run();
		}
		
		/**
		 * 
		 */
		public function testResultPropertiesNonNullityAfterRunningBenchs():void
		{
			benchRunner.addEventListener(
				BenchmarkEvent.CASE_RUNNED, 
				asyncHandler(async_testResultPropertiesNonNullityAfterRunningBenchs,50)
			);
			benchRunner.run();
		}
		
		private function async_testResultPropertiesNonNullityAfterRunningBenchs(event:BenchmarkEvent, data:Object):void
		{
			var result:TestResult = benchRunner.results[0];
			assertTrue(result.className != null);
			assertTrue(result.methodName != null);
			assertTrue(result.message != null);
			assertFalse(isNaN(result.duration));
		}
		
		/**
		 * 
		 */
		public function testResultConsistency():void
		{
			benchRunner.addEventListener(
				BenchmarkEvent.CASE_RUNNED, 
				asyncHandler(async_testResultConsistency, 50)
			);
			benchRunner.run();
		}
		
		private function async_testResultConsistency(event:BenchmarkEvent, data:Object):void
		{
			var result:TestResult = benchRunner.results[0];
			assertEquals(getQualifiedClassName(benchTest), result.className);
			assertEquals("benchMethod", result.methodName);			
			assertEquals(SimpleBenchTestMock.MESSAGE, result.message);
		}	
		
		/**
		public function testResultDurationShouldNotEqualZero():void
		{
			var message:String = "The result duration could probably not be equal to 0";
			assertTrue(message, result.duration !== 0);
		}
		*/
		
		public function testResultDurationShouldBeDifferentOnDifferentResults():void
		{
			benchTest = new LoudBenchTestMock;
			benchRunner = new CaseRunner(benchTest);
			benchRunner.run();
			
			var r1:TestResult,
				r2:TestResult,
				message:String = "Results should have different durations, " + 
								 "expected {0} to be different of {1}";
								 
			for each (r1 in benchRunner.results)
			{
				for each (r2 in benchRunner.results)
				{
					if(r1 != r2)
					{
						assertTrue(
							StringUtil.substitute(message, r1.duration, r2.duration), 
							r1.duration != r2.duration
						);	
					}
				}
			}
		}
		
		public function testResultsShouldHaveIncrementalDuration():void
		{
			benchTest = new LoudBenchTestMock;
			benchRunner = new CaseRunner(benchTest);
			benchRunner.addEventListener(
				BenchmarkEvent.CASE_RUNNED, 
				asyncHandler(async_testResultsShouldHaveIncrementalDuration, 50)
			);
			benchRunner.run();
		}
		
		private function async_testResultsShouldHaveIncrementalDuration(event:BenchmarkEvent, data:Object):void
		{
			var r:TestResult,
				d:Dictionary = new Dictionary;
			for each(r in (event.target as CaseRunner).results)
			{
				d[r.methodName] = r.duration;
			}
			
			assertTrue(d[LoudBenchTestMock.VERY_FAST_TEST] < d[LoudBenchTestMock.FAST_TEST]);
			assertTrue(d[LoudBenchTestMock.FAST_TEST] < d[LoudBenchTestMock.MEDIUM_TEST]);
			assertTrue(d[LoudBenchTestMock.MEDIUM_TEST] < d[LoudBenchTestMock.SLOW_TEST]);
		}
	}
}